//EFI controller v002
#include "main_set.h"

void main(void)
{
    int8    i,dis_swap=0;
    int16   j;
    int8    *P_fparm,*R_parm;
#if (1 == TRACE)
    int8 deb_cnt = 0;
#endif

//++++++++++++++++++ init hw +++++++++++++++++
    init_hw();
    lcd_init();
    lcd_cursor(1);
    lcd_clear();
    /* 1. row is on 0x00; 2. row is on 0x40; 3. row is on 0x14; 4. row is on 0x54 */
          //'------------------'
    lcd_putch("0123456789abcdef0123");   //first row
    lcd_goto(0x40);               //second row
    //lcd_putch(0x00);   // blank
    lcd_putch(0x01);   //
    lcd_putch(0x02);   // user symbols
    lcd_putch(0x03);   //
    lcd_putch(0x04);   //
          //'----------'first 4-user symbols
    lcd_putch("Test LCD !!!");
    lcd_putch(0x04);   //
    lcd_putch(0x03);   // user symbols
    lcd_putch(0x02);   //
    lcd_putch(0x01);   //
    lcd_goto(0x14);
              //'------------------'
    lcd_putch("EFI control 18F v0.2");
    lcd_goto(0x54);
          //'------------------'
    lcd_putch("First Fuel Inject!!!");
    beeper(100, 1);
    delay_ms(500); 
//+++++++++++++++++ Check i2c devices +++++++++++++++++
#if (1 == ENABLE_I2C_COMM)
    have_i2c_display = check_i2c_dev(I2C_DISPLAY_ADR, I2C_TIMEOUT);
    if(have_i2c_display) {
        msg_found_i2c_dev(I2C_DISPLAY_ADR, 100);
    } else {
        msg_not_found_i2c_dev(I2C_DISPLAY_ADR, 900);
    }
#endif

//+++++++++++++++++ set status redy MS +++++++++++++++++
    out_parm.engine = 0x00000001;    

//++++++++++++++++++copy fmap to ram +++++++++++++++++
    read_program_memory(&inpflash,&in_parm,sizeof(in_parm));

#if (0 == RPM_MAP_INDEX)
    in_parm.smap_table[0]= in_parm.fmap_table[0]= j= MAP_MIN;
    for (i = 1; i < NO_FMAPS; i ++) {
        j += MAP_S;
        in_parm.smap_table[i] = in_parm.fmap_table[i] = j;
    }
    in_parm.srpm_table[0] = in_parm.frpm_table[0] = j = REV_MIN;
    for (i = 1; i < NO_FRPMS; i ++) {
       j += REV_S;
       in_parm.srpm_table[i] = in_parm.frpm_table[i] = j;
    }
#endif
    // calculation start pulses
    prime_pulse_time = 
        (int16)((TMR_CONST * (in_parm.PrimeP + in_parm.InjOpen) * 100) / 1000);

//++++++++++++++++ calculate timer tick for max spark time ++++++++++++++
    spark_timer_tick = ms_x_10_to_tmr1_ticks(in_parm.max_spk_dur);

//++++++++++++++ Get initial baro and engine temperature ++++++++++++++++++++++
    set_adc_channel(0); //MAP sensor
    //delay_ms(1);//!!!!!!!!!!!!!!!!!!!!!!!!
    max_map_adc = read_adc(adc_start_and_read);
    max_baro=(int16)((1.0862*max_map_adc)+105.98); //ADC_START_AND_READ
    out_parm.baro=max_baro;
    rs_string[0]=0; // !!!!!!!!!!!!!!!! no send data via rs port
    acc_timer=0;
    
//++++++++++++++ Enable all needed interrupts forom hw +++++++++++++++++++
    enable_all_ints();

// ++++++++++++++++++ MAIN LOOP ++++++++++++++++++++++++++++++++
    out_parm.seconds = 0;
    while(TRUE) {
#ifdef ADC_SYNCH
        if (ad_ok==1) {
#endif

#if (1 == DEBUG_INT_2D)
            ad_ch[MAP_CH] = ADC_MAP;
            ad_ch[BAT_CH] = ADC_BAT;
#endif

#if (0 == INT_2D_MAP_BATT)
            k_pa =(int16)((1.0862*ad_ch[MAP_CH])+105.98);
            out_parm.batt = ad_ch[BAT_CH]/ADC_CONST; //V x10  ad_ch[1]
#else
            k_pa = (unsigned int16) inter_2d (
                        (signed int16) ad_ch[MAP_CH],
                        (signed int16) 0
                        (signed int16) 1023,
                        (signed int16) in_parm.map0,
                        (signed int16) in_parm.mapmax);
            
            out_parm.batt = (unsigned int16) inter_2d (
                        (signed int16) ad_ch[BAT_CH],
                        (signed int16) 0
                        (signed int16) 1023,
                        (signed int16) in_parm.batt0,
                        (signed int16) in_parm.battmax);
#endif

#if (1 == DEBUG_TABLES )
            k_pa = MAP_D;
            oboroti = REV_D;
#endif
            // TODO: there are no adc channel for WB O2 sensor
            if (in_parm.EgoOption >= 2) {
                //afr x 10
                out_parm.ego1 = out_parm.ego2 = (int16)
                    (0.147 * /* put adc channel fo WB O2 sensor here*/ad_ch[TPS_CH])
                        + 73.5;
            }

            bar_percent=(int8)(((float)k_pa/(float)max_baro)*100);
            //out_parm.tps = (int16) bar_percent*10;
            //+++++++++++++++++++  tps sensor % reading +++++++++++++++++++++++++++++++++++++
            if (ad_ch[TPS_CH]< in_parm.tps0) {
                ad_ch[TPS_CH] = in_parm.tps0;
            }

            if (ad_ch[TPS_CH]> in_parm.tpsmax) {
                ad_ch[TPS_CH] = in_parm.tpsmax;
            }
            //out_parm.tps = (int16)((((int32)ad_ch[3] - in_parm.tps0)*1000)/(in_parm.tpsmax - in_parm.tps0));
            out_parm.tps = (int16)((((int32)ad_ch[TPS_CH] - in_parm.tps0)*1000)/
                                            (in_parm.tpsmax - in_parm.tps0));
            out_parm.map=k_pa;

#if (1 == DEBUG_TABLES)
            out_parm.batt = BATT_D;
#endif
            out_parm.tpsdot = out_parm.tps - last_tps;
            last_tps = out_parm.tps;
            out_parm.mapdot = k_pa - last_k_pa;
            last_k_pa = k_pa;
            //out_parm.clt = 978 - (10.3*(ad_ch[1]*10)/(ad_ch[1]-ad_ch[2]));//978 - (10,3*A23)
            /* this cal culation is refresh dtata loop */ 
            //temp_resistor = (((int32)ad_ch[2]*TEMP_BRIGE)/(ad_ch[1]-ad_ch[2]));
            //out_parm.clt=(signed int)2282-(299*(log(temp_resistor)));
            out_parm.spare1 = ad_ch[MAP_CH]; //ad_ch[0];
            out_parm.spare2 = ad_ch[BAT_CH]; //ad_ch[1];
            out_parm.spare3 = ad_ch[TMP_CH]; //ad_ch[2];
            out_parm.spare4 = ad_ch[TPS_CH]; //ad_ch[3];

//++++++++++++++++  warmup enrichment ++++++++++++++++++++++++++++++++++++++++++++++++++++  
#if (1 == DEBUG_TABLES)
                        out_parm.clt = COLT_D;
#endif

            //out_parm.clt = -170; ///debug
            if (out_parm.clt < in_parm.temp_table[NO_TEMPS-1]) {

                out_parm.engine |=(1<<3); //set warm up en

                if(out_parm.clt < in_parm.temp_table[0]) {
                    for (i=NO_TEMPS-1; i > 0 ; i--) {
                        if(out_parm.clt > in_parm.temp_table[i-1]) {
                            idx_temp = i-1;
                            break;
                        }
                    }
                } else {
                    idx_temp = 0;
                }
#if 0                
                pw_corr_per_w = in_parm.warmen_table[idx_temp];
#else
                pw_corr_per_w = (unsigned int8) inter_2d (
                                (signed int16) out_parm.clt,
                                (signed int16) in_parm.temp_table[idx_temp],
                                (signed int16) in_parm.temp_table[idx_temp+1],
                                (signed int16) in_parm.warmen_table[idx_temp],
                                (signed int16) in_parm.warmen_table[idx_temp+1]);
#endif
            } else if (pw_corr_per_w > 100) {
                pw_corr_per_w = 100;
                out_parm.engine &= ~(1<<3); //clear warm up en
            }

            //after start enrichment applys
            if (cycles) {
                pw_corr_per_w += in_parm.AWEV; //cycles = AWC -number of cycles;
            }   

//==================== acceration enrichment based on TPS Sensor ++++++++++++++++++++++++++
//                                          TO DO
            if ((int8)abs(out_parm.tpsdot) > in_parm.TpsThresh) {
                if (out_parm.tpsdot > 0) {
                    for (i = NO_TPS_DOTS - 1; i > 0; i--) {
                        if (out_parm.tpsdot > in_parm.tpsdot_table[i-1]) {
                                //remove interpolation to debug overflow pw_acc
                                //(y1+(((y2-y1)*(x-x1)))/(x2-x1));

#if 1
                                    pw_acc_tps= (int8) inter_2d (
                                        (signed int16) out_parm.tpsdot,
                                        (signed int16) in_parm.tpsdot_table[i-1],
                                        (signed int16) in_parm.tpsdot_table[i],
                                        (signed int16) in_parm.tpsen_table[i-1],
                                        (signed int16) in_parm.tpsen_table[i]);
#else
                                    pw_acc_tps= ((in_parm.tpsen_table[i] - in_parm.tpsen_table[i-1]) *
                                    (out_parm.tpsdot - in_parm.tpsdot_table[i-1]) /
                                    (in_parm.tpsdot_table[i] - in_parm.tpsdot_table[i-1]))
                                    + in_parm.tpsen_table[i];
#endif
                                break;
                        }
                    }
                    out_parm.engine |= (1<<4); //set tps acc en
                    out_parm.engine &= ~(1<<5); //clear tps deacc en
                } else {
                    de_acc=1;
                    out_parm.engine &= ~(1<<4); //clear tps acc en
                    out_parm.engine |= (1<<5); //set tps deacc en
                }
            } else {
                out_parm.engine &= ~(1<<5); //clear tps deacc en
                out_parm.engine &= ~(1<<4); //clear tps acc en
            }

//==================== acceration enrichment based on MAP Sensor ++++++++++++++++++++++++++
//              out_parm.mapdot = in_parm.mapdot_table[0]+2;
//            if (out_parm.mapdot > in_parm.mapdot_table[0] && acc_timer==0)
#if 0
            if (out_parm.mapdot > in_parm.mapdot_table[0]) {
                for (i=1; i<NO_MAP_DOTS; i++) {
                    if (out_parm.mapdot < in_parm.mapdot_table[i]) {
                        // this case should be changed
                        if (pw_acc_map < in_parm.mapen_table[i-1]) {
                            //pw_acc=in_parm.mapen_table[i-1]; 
                            //interpolation of enrichment table 
                            //i =  inter_2d ( (signed) out_parm.mapdot, (signed) in_parm.mapdot_table[i-1], (signed) in_parm.mapdot_table[i], (signed int16) in_parm.mapen_table[i-1], (signed int16) in_parm.mapen_table[i]);
                            pw_acc_map= inter_2d (
                                out_parm.mapdot,
                                in_parm.mapdot_table[i-1],
                                in_parm.mapdot_table[i],
                                in_parm.mapen_table[i-1],
                                in_parm.mapen_table[i]);
                            // acc_timer = in_parm.TpsAsync;
                        }
                        break;
                    }
                    
                    if (i==NO_MAP_DOTS-1) {
                        pw_acc_map=in_parm.mapen_table[i];
                        //acc_timer = in_parm.TpsAsync;
                        break;
                    }
                }
                //out_parm.engine |=(1<<4); //set tps acc
                //out_parm.engine &=~(1<<6); //clear map deacc bit
                //de_pw_acc = -(((out_parm.pw1/100)*in_parm.TPSDQ)/100);
            } else if ((out_parm.mapdot < 0) && 
                (in_parm.MapThresh < (int16)abs(out_parm.mapdot))) {
                //if(pw_acc >0){ pw_acc=0; }
                //   pw_acc=-((((out_parm.pw1/100)*in_parm.TPSDQ)/100)-pw_acc);
                //  pw_acc= de_pw_acc;
                //   printf ("%d - %Lu;",pw_acc, out_parm.pw1);
                pw_acc_map=0;// = tail_off_timer = acc_timer = 0;				// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                //      pw_corr_per=100-in_parm.TPSDQ;
                //out_parm.engine &=~(1<<4); //clear tps acc
                out_parm.engine |=(1<<6); //set map deacc bit
                //acc_timer = in_parm.TpsAsync;
            } else {
                //out_parm.engine &=~(1<<4); //clear tps acc
                out_parm.engine &=~(1<<6); //clear map deacc bit
            }
#else
            if ((int8)abs(out_parm.mapdot) > in_parm.MapThresh) {
                if (out_parm.mapdot > 0) {
                    for (i = NO_TPS_DOTS - 1; i > 0; i--) {
                        if (out_parm.mapdot > in_parm.mapdot_table[i-1]) {
#if 1
                                    pw_acc_map= (int8) inter_2d (
                                        (signed int16) out_parm.mapdot,
                                        (signed int16) in_parm.mapdot_table[i-1],
                                        (signed int16) in_parm.mapdot_table[i],
                                        (signed int16) in_parm.mapen_table[i-1],
                                        (signed int16) in_parm.mapen_table[i]);
#else
                                    pw_acc_map= ((in_parm.mapen_table[i] - in_parm.mapen_table[i-1]) *
                                    (out_parm.mapdot - in_parm.mapdot_table[i-1]) /
                                    (in_parm.mapdot_table[i] - in_parm.mapdot_table[i-1]))
                                    + in_parm.mapen_table[i];
#endif
                                break;
                        }
                    }
                    out_parm.engine |=(1<<6);   //set map acc en
                    //out_parm.engine &=~(1<<5);  //clear tps deacc en
                } else {
                    de_acc=1;
                    out_parm.engine &=~(1<<6);  //clear map acc en
                    //out_parm.engine |=(1<<5);   //set tps deacc en
                }
            } else {
                //out_parm.engine &=~(1<<5);      //clear tps deacc en
                out_parm.engine &=~(1<<6);      //clear tps acc en
            }
#endif

//  +++++++++++++++++++++++ Final acc based on Tps_acc_widht parameter ++++++++++++++++++++++++++++++++++  
//  My be map_dot treshhold is too low try to set only MAP or TPS only  for debug only see acc_enricment in log files 
            out_parm.tps_acc_en = pw_acc_tps;
            out_parm.map_acc_en = pw_acc_map;

            if ((pw_acc_tps > 0) || (pw_acc_map > 0)) {
                //pw_acc = (int8)(((int16)pw_acc_tps * in_parm.Tps_acc_wght) + (((int16)pw_acc_map * (100 - in_parm.Tps_acc_wght))) / 100);
                //pw_acc_tmp = (int8)((((int16)pw_acc_tps * in_parm.Tps_acc_wght)/100) + ((((int16)pw_acc_map * (100 - in_parm.Tps_acc_wght))) / 100));
                pw_acc_tmp = ((int8) (((int16)pw_acc_tps * in_parm.Tps_acc_wght)/100) +
                    (int8)((((int16)pw_acc_map * (100 - in_parm.Tps_acc_wght))) / 100));

                if (pw_acc_tmp > pw_acc_last) {
                    /* put pw_acc_tmp in pw_acc to be done in pw_acc and lock it in pw_acc_last  
                                    pw_acc_last will be cleared in real time interrupt (timer 3) */
                    pw_acc_last = pw_acc = pw_acc_tmp;
                    tail_off_step = (pw_acc - (char)in_parm.TpsAccel2) / in_parm.TpsAsync2;
                                        tail_off_timer = (char) in_parm.TpsAsync2; 
                    acc_timer = (char) in_parm.TpsAsync;
                    //pw_acc = pw_acc_tps;
                    //pw_acc_tps = pw_acc_map = 0;
                }
            } else if (de_acc) {
                pw_acc_last = de_acc = tail_off_timer = 
                    acc_timer = pw_acc = 0;
            }

            pw_acc_tps = pw_acc_map = 0;            
            out_parm.tpsaccel = (int16)pw_acc;
            out_parm.last_acc = (int16)pw_acc_last;
#ifdef ADC_SYNCH
            ad_ok=0;    //flag will be set when all adc channels are done
        }
#endif
        //inter_3d(10, 10, 10, 10, 10, 10, 10, 10, 10, 10);
//================ Calculate engine speed ++++++++++++++++++++++++++
        time = time_fok + time_rok;
        oborotit = oboroti;
        //oboroti =(int16) (300*CYCLE/(time*DIV));      //TMR1 1:4=>8e-6 1:2=>4e-6
        oboroti = timer_to_rpm(time);

//debug position offset in distributor
//             0    1     2     3
//       _--__--__--__--_-
//         0     1     2     3

        time_1 = 0;
        for (i= 0; i < COUNT_MAX; i++) {
            time_1 += (ign_chanel_fall[i] + ign_chanel_rise[i]); 
        }

        for (i= 0; i < COUNT_MAX; i++) {
            // 180, 360,  540, 720 (0) deg x 10
            //relative offset_ign_chanel 180deg
#if 1
        offset_ign_chanel[i] = tmr1_ticks_to_degr(time_1,
            (ign_chanel_fall[i] + ign_chanel_rise[i]));
#else
            offset_ign_chanel[i] = ign_chanel_fall[i] + ign_chanel_rise[i];
#endif
        }
        
//================ break engine mode ++++++++++++++++++++++++++++=
        if ((oboroti > REV_MIN_F_CUT)&&
                (k_pa < (MAP_MIN - MAP_MIN_F_CUT))) {
            //swap fuel cut mode
            //pw_corr_per_brk=100-in_parm.TPSDQ;
            pw_corr_per_brk = in_parm.TPSDQ;
        } else if (pw_corr_per_brk < 100) {
            pw_corr_per_brk = 100;
        }
        
        if ( pw_corr_per_brk != 100 ) {
            pw_corr_per = pw_corr_per_brk;
        } else if ( pw_corr_per_w != 100 ) {
            pw_corr_per = pw_corr_per_w;
        } else {
            pw_corr_per = 100;
        }
        
        out_parm.warmcor = (int16) pw_corr_per_w;            
        out_parm.tpsfuelcut = (int16) pw_corr_per_brk;
        out_parm.gammae = (int16) pw_corr_per;

#if (1 == DEBUG_TABLES)
        k_pa = MAP_D;
        oboroti = REV_D;
#endif
        out_parm.rpm = oboroti;
        diff = oboroti - oborotit;
        pul = (time_fok) / (time/100);

#if (0 == RPM_MAP_INDEX)
        if ((MAP_MIN < k_pa)&&(k_pa < MAP_MAX)) {
            mapt = (k_pa - MAP_MIN) / MAP_S;
        } else if (MAP_MAX < k_pa) {
            mapt = 10;
        } else {
            mapt = 0;
        }
            
        if ((REV_MIN < oboroti)&&(oboroti < REV_MAX)) {
            obt = (oboroti - REV_MIN) / REV_S;
        } else if (REV_MAX < oboroti) {
            obt = 10;
        } else {
            obt = 0;
        }
#else

//+++++++++++++++  Find tables index  =====================
        if (oboroti > in_parm.frpm_table[0]) {
            for (i = NO_FRPMS-1; i > 0; i--) {
                if (oboroti > in_parm.frpm_table[i-1]) {
                    obt = i-1;
                    break;
                }            
            }
        } else {
            obt = 0;
        }
        
        if (k_pa > in_parm.fmap_table[0]){
            for (i = NO_FMAPS-1; i > 0; i--) {
                if (k_pa > in_parm.fmap_table[i-1]) {
                    mapt = i - 1;
                    break;
                }
            }
        } else {
            mapt = 0;
        }
#endif

//+++++++++++++++ Get degree from adv table ================
        out_parm.adv_deg= ign_table_out= get_ign_deg(obt, mapt, &in_parm);
        //ign_timer_in = ((time / 720)*ign_table_out)/10;
        //ign_offset_timer_tick = ((time / 720)*in_parm.adv_offset)/10;
        ign_timer_in = degr_to_tmr1_ticks(time,(ign_table_out + in_parm.adv_offset));
        calc_wb_corretions();
        if(!(deb_inj)) {
            tableinter();   //!!!
        }

        if (refresh_data) {
            //Delay_ms (10); //only debug sim !!!
            refresh_data = 0;
            //temp_resistor = (((int32)ad_ch[2]*TEMP_BRIGE)/(ad_ch[1]-ad_ch[2]));
            temp_resistor = (((int32)ad_ch[TMP_CH] * TEMP_BRIGE)/
                                (ad_ch[BAT_CH] - ad_ch[TMP_CH]));
            out_parm.clt = (signed int)2282 - (299 * (log(temp_resistor)));
            //printf( "ch1: %Lu. ch2: %Lu. res: %Ld.\r\n",ad_ch[1],ad_ch[2],(signed int32)temp_resistor);/
                
#if (1 == DEBUG_TABLES)
                k_pa            = MAP_D;
                oboroti         = REV_D;
                out_parm.clt    = COLT_D;
                out_parm.batt   = BATT_D;
                last_bat = 0;
#endif
//++++++++++++++++ check for power up engine ===========================
            if (abs(out_parm.batt - last_bat) > BATT_PRIME_DIFF &&
                (out_parm.batt > last_bat)) {

                //calculate crank pulse width
                pulse_crank = (unsigned int8) inter_2d (  //ms X10
                                (signed int16) out_parm.clt,
                                (signed int16) in_parm.temp_table[0],
                                (signed int16) in_parm.temp_table[NO_TEMPS - 1],
                                (signed int16) in_parm.CWU,
                                (signed int16) in_parm.CWH);

                pulse_crank += (((signed int8) in_parm.BatFac *
                    (132 - out_parm.batt)) / 60) + in_parm.InjOpen; // open time correction ms X10

                timeinj_crank = (unsigned int16)((TMR_CONST * pulse_crank) / 10);    //loss of the resolution

                //prime pulse enable if engine is cold
                if(out_parm.clt < ENGINE_PRIME_TEMP) {
                    delay_ms(1000);                 //let fuel pump reaches a fuel preshure
                    out_parm.engine |= (1 << 1);    //set engine crank for MS
                    prime_pul = 1;
                    ign_power_up = 1;
                    cycles = in_parm.AWC;           // load start up pulse count
                    beeper(100, 3);
                } else {
                    beeper(100, 1);
                }
            }
 
            last_bat = out_parm.batt;

            //check if engine is in runing state
            if (oboroti) {
                ign_power_up = 0;
                out_parm.engine &= ~(1 << 1);   //clear engine crank for MS
            } else {
                out_parm.engine |= (1 << 1);    //set engine crank for MS
                ign_power_up = 1;
#if 0
                if (in_parm.TPSWOT < out_parm.tps) {
                    //flood clear - mode disable ingnition event interrupt
                    disable_interrupts(INT_RB);
                } else if(!is_rb_isr_enabled()) {
                    //flood clear - mode enable ingnition event interrupt
                    clear_interrupt(INT_RB);
                    enable_interrupts(INT_RB);
                }
#endif
            }
            
            /* lo oboroti - calculate display bars*/    
            if (oboroti > 600) {
                barob=((oboroti - 530) / 174) / 5;
                barobd=(((oboroti - 530) / 174) - (barob * 5));
            } else {
                barob = 0;
                barobd = 0;
            }

            if (bar_percent < 101) {
                barv=((bar_percent / 2.5) / 5);               
                barvd=((bar_percent / 2.5) - (barv * 5));       
            }

            if (!ign_power_up) {

                bar_p_inj=(int8)(out_parm.pw1 / TIME_INJ_SCALE);
                if (bar_p_inj < 101) {
                    barinj=((bar_p_inj / 2.5) / 5);
                    barinjd=((bar_p_inj / 2.5) - (barinj * 5));
                }
                
            } else {
                // pulse_crank pulsewidths  (ms x 10) bar uses a us
                bar_p_inj=(int8)(((int16)pulse_crank * 100) / TIME_INJ_SCALE);
                if (bar_p_inj < 101) {
                    barinj=((bar_p_inj / 2.5) / 5);
                    barinjd=((bar_p_inj / 2.5) - (barinj * 5));
                }
            }
            
            kb_input();
            if (!freeze_dispaly) {
                if (dis_swap < SWAP_DISPLAY_COUNT) {
                    dis_swap ++;
                } else {
                    dis_swap = 0;
                    if (display_mode < MAX_DISPLAY) {
                        display_mode ++;
                    } else {
                        display_mode = NORMAL;
                    }
                }
            }

            f_count += time_to_liter(pw_count);
            pw_count = 0;

#if 1 // debug offset
            #warning display_mode = IGN_3;
            display_mode = IGN_3;
#endif

            switch (display_mode) {
                default:
                case NORMAL:
                    new_dis(MODE_DEF);
                    break;
                case FUEL:
                    new_dis(MODE_FUEL);
                    break;
                case FUEL_MY:
                    new_dis(MODE_FUEL_NEW);
                    break;
                case ADC:
                    display_adc();
                    break;
#if(1 == PROTEUS_SIM)
                case IGN_1:
                    dispaly_ign_time(IGN_1);
                    break;
                case IGN_2:    
                    dispaly_ign_time(IGN_2);
                    break;
                case IGN_3:    
                    dispaly_ign_time(IGN_3);
                    break;
#else
                case IGN_1:
                case IGN_2:
                case IGN_3:
                    dispaly_ign_time(display_mode);
                    break;
                case KPA:
                    display_env();
                    break;
#endif
            }    

            set_menu();
        }

//===============burn settings=======================
        if (burn_flag) {
            //disable_interrupts(GLOBAL);
            burn_flag = 0;
            P_fparm = &inpflash;
            R_parm = &in_parm;
            j = sizeof(in_parm) / FLASH_BLOCK_SIZE;

#ifndef BURN_DISABLE
            for ( i = 0; i < j; i++) {
                write_program_memory (P_fparm,R_parm,FLASH_BLOCK_SIZE);
                P_fparm += FLASH_BLOCK_SIZE;
                R_parm += FLASH_BLOCK_SIZE;
            }

            i = sizeof(in_parm) - (j*FLASH_BLOCK_SIZE);
            write_program_memory (P_fparm,R_parm,i);
#endif
            beeper(50, 2);
            //delay_ms (100);
            //RST=1;
            //enable_interrupts(GLOBAL);
        }

//!!!!!!!!!!! RESET TO RUN BOOT LOADER !!!!!!!!!!!!!
        if(RST) {
            RST=deb_inj=0;
            msg_bootloader();
            INJ_CLOSE
            reset_cpu();
        }
    }
}

